﻿using System.Runtime.Versioning;
using Zhp.Common.Extention;
using Zhp.Common.Helper;
using Zhp.IService.Monitor;
using Zhp.Model.Monitor;

namespace Zhp.Service.Monitor
{
    [SupportedOSPlatform("linux")]
    [SupportedOSPlatform("windows")]
    public class ServerResourceService : IServerResourceService
    {
        private const int B = 1;
        private const int Kb = 1024 * B;
        private const int Mb = 1024 * Kb;
        private const int Gb = 1024 * Mb;

        public async Task<ServerResourceModel> Query()
        {
            var os = new OsInfoTo();

            ServerResourceModel osInfo = new ServerResourceModel
            {
                Time = DateTime.Now.ToString("HH:mm:ss"),
                Sys = new Model.Monitor.Sys
                {
                    Os = os.OsDescription,
                    Day = DateTimeHelper.FormatLongToTime(os.TickCount),
                    Ip = os.LocalIp,
                },
                Cpu = new Cpu
                {
                    Name = os.ProcessorName,
                    Package = os.PhysicalProcessorCount + "个物理CPU",
                    Core = os.NumberOfCores + "个物理核心",
                    CoreNumber = os.NumberOfCores,
                    Logic = os.LogicProcessorCount + "个逻辑CPU",
                    Used = os.ProcessorUtilizationRate,
                    Idle = (100 - os.ProcessorUtilizationRate)
                },
                Memory = new Memory
                {
                    Total = Math.Round(Convert.ToDecimal(os.TotalPhysicalMemory) / Gb, 2).ToString("0.00") + " GiB",
                    Used = Math.Round(Convert.ToDecimal(os.TotalPhysicalMemory - os.FreePhysicalMemory) / 1073741824, 2).ToString("0.00") + " GiB",
                    Available = Math.Round(Convert.ToDecimal(os.FreePhysicalMemory) / Gb, 1).ToString("0.00") + " GiB",
                    UsageRate = Math.Round(100 / Math.Round(Convert.ToDecimal(os.TotalPhysicalMemory) / 1073741824, 2) * Math.Round(Convert.ToDecimal(os.TotalPhysicalMemory - os.FreePhysicalMemory) / Gb, 2), 2)
                },
                Swap = new Swap(),
                Disk = new Model.Monitor.Disk()
            };
            if (os.LogicalDisk is { Count: > 0 })
            {
                long size = 0;
                long freeSpace = 0;
                foreach (var item in os.LogicalDisk)
                {
                    size += item.Size;
                    freeSpace += item.FreeSpace;
                }

                osInfo.Disk.Total = Math.Round(Convert.ToDecimal(size) / Gb, 2).ToString("0.00") + " GiB";
                osInfo.Disk.Used = Math.Round(Convert.ToDecimal(size - freeSpace) / Gb, 2).ToString("0.00") + " GiB";
                osInfo.Disk.Available = Math.Round(Convert.ToDecimal(freeSpace) / Gb, 2).ToString("0.00") + " GiB";
                osInfo.Disk.UsageRate = Math.Round(100 / Math.Round(Convert.ToDecimal(size) / Gb, 2) * Math.Round(Convert.ToDecimal(size - freeSpace) / Gb, 2), 2);
            }

            if (os.SwapTotal > 0)
            {
                osInfo.Swap.Total = Math.Round(Convert.ToDecimal((int)(os.SwapTotal / Gb)), 2).ToString("0.00") + " GiB";
                osInfo.Swap.Used = Math.Round(Convert.ToDecimal((int)((os.SwapTotal - os.SwapFree) / Gb)), 2).ToString("0.00") + " GiB";
                osInfo.Swap.Available = Math.Round(Convert.ToDecimal((int)(os.SwapFree / Gb)), 2).ToString("0.00") + " GiB";
                osInfo.Swap.UsageRate = Math.Round(Convert.ToDecimal((int)(100 / os.SwapTotal * (os.SwapTotal - os.SwapFree))), 2);
            }

            return await Task.FromResult(osInfo);
        }
    }
}
